home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / c / agl103p.lha / src / agl / que.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-09  |  22.2 KB  |  1,111 lines

  1. /******************************************************************************
  2.  
  3. Copyright © 1994 Jason Weber
  4. All Rights Reserved
  5.  
  6. $Id: que.c,v 1.2.1.5 1994/12/09 05:29:56 jason Exp $
  7.  
  8. $Log: que.c,v $
  9.  * Revision 1.2.1.5  1994/12/09  05:29:56  jason
  10.  * border buttons with feedback
  11.  *
  12.  * Revision 1.2.1.4  1994/11/16  06:28:44  jason
  13.  * border support
  14.  *
  15.  * Revision 1.2.1.3  1994/09/13  03:52:07  jason
  16.  * replaced micropause() with delay()
  17.  *
  18.  * Revision 1.2.1.2  1994/04/06  02:42:15  jason
  19.  * Now only updates que when it's empty
  20.  *
  21.  * Revision 1.2.1.1  1994/03/29  05:41:32  jason
  22.  * Added RCS Header
  23.  
  24. ******************************************************************************/
  25.  
  26.  
  27. #ifndef NOT_EXTERN
  28. #include"agl.h"
  29. #endif
  30.  
  31. #include"keymap.h"
  32.  
  33.  
  34. #define QDEBUG            FALSE
  35.  
  36. #define MAXKEYINPUT        128
  37.  
  38. #define BORDER_TITLE    0
  39. #define BORDER_LEFT        1
  40. #define BORDER_RIGHT    2
  41. #define BORDER_TOP        4
  42. #define BORDER_BOTTOM    8
  43. #define BORDER_MENU        16
  44. #define BORDER_MINIMIZE    32
  45. #define BORDER_MAXIMIZE    64
  46.  
  47.  
  48. struct InputEvent InEvent={0,IECLASS_RAWKEY,0,0,0};
  49.  
  50. short LastOrigin[MAX_WINDOWS][2];
  51. short Tie[MAX_DEVICE][2];
  52. short Queued[MAX_DEVICE];
  53. short ButtonState[MAX_DEVICE];
  54. short QRead,QWrite;
  55. short Mousex,Mousey,LastMousex=0,LastMousey=0;
  56. short Mouse2x=0,Mouse2y=0;
  57.  
  58. long Queue[QUEUE_SIZE][2];
  59.  
  60.  
  61.  
  62. /******************************************************************************
  63. void    qinit(void)
  64.  
  65. ******************************************************************************/
  66. /*PROTOTYPE*/
  67. void qinit(void)
  68.     {
  69.     short m;
  70.  
  71.     GLFocus=0;
  72.  
  73.     QRead=0;
  74.     QWrite=0;
  75.  
  76.     for(m=0;m<MAX_WINDOWS;m++)
  77.         {
  78.         LastOrigin[m][0]= -1;
  79.         LastOrigin[m][1]= -1;
  80.         }
  81.  
  82.     for(m=0;m<MAX_DEVICE;m++)
  83.         {
  84.         Queued[m]=FALSE;
  85.         Tie[m][0]=0;
  86.         Tie[m][1]=0;
  87.         }
  88.  
  89.     clear_buttons(TRUE);
  90.  
  91.     Queued[REDRAW]=TRUE;
  92.     Queued[INPUTCHANGE]=TRUE;
  93.     }
  94.  
  95.  
  96. /******************************************************************************
  97. void    tie(long dev,long valuator1,long valuator2)
  98.  
  99. ******************************************************************************/
  100. /*PROTOTYPE*/
  101. void tie(long dev,long valuator1,long valuator2)
  102.     {
  103.     Tie[dev][0]=valuator1;
  104.     Tie[dev][1]=valuator2;
  105.     }
  106.  
  107.  
  108. /******************************************************************************
  109. void    qdevice(long dev)
  110.  
  111. ******************************************************************************/
  112. /*PROTOTYPE*/
  113. void qdevice(long dev)
  114.     {
  115.     Queued[dev]=TRUE;
  116.     }
  117.  
  118.  
  119. /******************************************************************************
  120. void    unqdevice(long dev)
  121.  
  122. ******************************************************************************/
  123. /*PROTOTYPE*/
  124. void unqdevice(long dev)
  125.     {
  126.     Queued[dev]=FALSE;
  127.     }
  128.  
  129.  
  130. /******************************************************************************
  131. long    isqueued(long dev)
  132.  
  133. ******************************************************************************/
  134. /*PROTOTYPE*/
  135. long isqueued(long dev)
  136.     {
  137.     return Queued[dev];
  138.     }
  139.  
  140.  
  141. /******************************************************************************
  142. void    qenter(long dev,short val)
  143.  
  144. ******************************************************************************/
  145. /*PROTOTYPE*/
  146. void qenter(long dev,short val)
  147.     {
  148.     Queue[QWrite][0]=dev;
  149.     Queue[QWrite][1]=val;
  150.     QWrite++;
  151.  
  152.     if(QWrite==QRead)
  153.         {
  154.         GL_error("Queue filled: event overrun");
  155.         QRead++;
  156.         if(QRead==QUEUE_SIZE)
  157.             QRead=0;
  158.         }
  159.  
  160.     if(QWrite==QUEUE_SIZE)
  161.         QWrite=0;
  162.     }
  163.  
  164.  
  165. /******************************************************************************
  166. long    qtest(void)
  167.  
  168.     checks if there is event in the queue
  169.     doesn't wait, returns immediately
  170.  
  171. ******************************************************************************/
  172. /*PROTOTYPE*/
  173. long qtest(void)
  174.     {
  175.     if(QRead==QWrite)
  176.         update_queue(-1);
  177.  
  178.     if(QRead==QWrite)
  179.         return 0;
  180.     else
  181.         return Queue[QRead][0];
  182.     }
  183.  
  184.  
  185. /*******************************************************************************
  186. void    delay(void)
  187.  
  188. *******************************************************************************/
  189. /*PROTOTYPE*/
  190. void delay(void)
  191.     {
  192.     Delay(5);
  193.     }
  194.  
  195.  
  196. /******************************************************************************
  197. long    qread(short *data)
  198.  
  199.     reads queue
  200.     will wait for an event
  201.  
  202. ******************************************************************************/
  203. /*PROTOTYPE*/
  204. long qread(short *data)
  205.     {
  206.     long device;
  207.  
  208.     while(QRead==QWrite)
  209.         {
  210.         update_queue(-1);
  211.         delay();
  212.         }
  213.  
  214.     device=Queue[QRead][0];
  215.     *data=Queue[QRead][1];
  216.  
  217.     QRead++;
  218.  
  219.     if(QRead==QUEUE_SIZE)
  220.         QRead=0;
  221.  
  222.     return device;
  223.     }
  224.  
  225.  
  226. /******************************************************************************
  227. void    qreset(void)
  228.  
  229. ******************************************************************************/
  230. /*PROTOTYPE*/
  231. void qreset(void)
  232.     {
  233.     QRead=QWrite;
  234.     }
  235.  
  236.  
  237. /******************************************************************************
  238. long    getvaluator(long val)
  239.  
  240. ******************************************************************************/
  241. /*PROTOTYPE*/
  242. long getvaluator(long val)
  243.     {
  244.     long result=0;
  245.  
  246.     switch(val)
  247.         {
  248.         case MOUSEX:
  249.             result=GLScreen->MouseX;
  250.             break;
  251.         case MOUSEY:
  252.             result=GLScreen->Height-1-GLScreen->MouseY;
  253.             break;
  254.         }
  255.  
  256.     return result;
  257.     }
  258.  
  259.  
  260. /******************************************************************************
  261. long    getbutton(long num)
  262.  
  263. ******************************************************************************/
  264. /*PROTOTYPE*/
  265. long getbutton(long num)
  266.     {
  267.     update_queue(-1);
  268.  
  269.     return (long)ButtonState[num];
  270.     }
  271.  
  272.  
  273. /******************************************************************************
  274. void clear_buttons(long init)
  275.  
  276.     resets state of mouse buttons
  277.  
  278.     unless init, issues que entry for switch off
  279.  
  280. ******************************************************************************/
  281. /*PROTOTYPE*/
  282. void clear_buttons(long init)
  283.     {
  284.     long m;
  285.  
  286. /*     printf("clear buttons\n"); */
  287.  
  288.     for(m=0;m<MAX_DEVICE;m++)
  289.         {
  290.         if(ButtonState[m] && Queued[m] && !init)
  291.             qenter_tie(m,(short)FALSE);
  292.  
  293.         ButtonState[m]=FALSE;
  294.         }
  295.     }
  296.  
  297.  
  298. /*******************************************************************************
  299. void    update_queue(short waitid)
  300.  
  301.     a manual MOUSEX,MOUSEY move check is much better than having Intuition
  302.         flood the system with reports
  303.  
  304.     if waitid>=0, wait for event in wid specified by waitid
  305.  
  306. *******************************************************************************/
  307. /*PROTOTYPE*/     
  308. void update_queue(short waitid)
  309.     {
  310.     struct IntuiMessage *message,*mess1,*mess2;
  311.     struct MsgPort *userport;
  312.  
  313.     ULONG class;
  314.     USHORT code;
  315.     UWORD qualifier;
  316.  
  317.     char string[MAXKEYINPUT];
  318.  
  319.     long wid,old_wid;
  320.     long border_touch=NULL;    /* wid of window whose border is being touched */
  321.     long device;
  322.     long originx,originy;
  323.     long sizex,sizey;
  324.  
  325.     short inside;
  326.     short border;
  327.     short data;
  328.     short ascii;
  329.     short c;
  330.     short length;
  331.     short mx,my;
  332.     short waited=FALSE;
  333.  
  334.     Mousex=getvaluator(MOUSEX);
  335.     Mousey=getvaluator(MOUSEY);
  336.  
  337. #if MICE
  338.     while(gameport_event(&device,&data,&mx,&my))    /* mx,my = delta mouse position */
  339.         {
  340. /*
  341.         if(device && Queued[device])
  342.             qenter_tie(device,data);
  343. */
  344.             
  345.         if(mx || my)
  346.             {
  347.             Mouse2x+=mx;
  348.             Mouse2y+=my;
  349.  
  350.             if(Mouse2x<0)
  351.                 Mouse2x=0;
  352.             if(Mouse2x>GLScreen->Width-1)
  353.                 Mouse2x=GLScreen->Width-1;
  354.  
  355.             if(Mouse2y<0)
  356.                 Mouse2y=0;
  357.             if(Mouse2y>GLScreen->Height-1)
  358.                 Mouse2y=GLScreen->Height-1;
  359.  
  360. /*
  361.             if(Queued[BPADX])
  362.                 qenter(BPADX,Mouse2x);
  363.  
  364.             if(Queued[BPADY])
  365.                 qenter(BPADY,Mouse2y);
  366. */
  367.  
  368.             move_mousesprite((long)Mouse2x,(long)Mouse2y);
  369.             }
  370.         }
  371. #endif
  372.  
  373.     if( (Queued[MOUSEX]||Queued[MOUSEY]) && (Mousex!=LastMousex||Mousey!=LastMousey)
  374.                                                         && is_inside(GLFocus,Mousex,Mousey,FALSE) )
  375.         {
  376.         if(Queued[MOUSEX])
  377.             qenter(MOUSEX,Mousex);
  378.         if(Queued[MOUSEY])
  379.             qenter(MOUSEY,Mousey);
  380.         }
  381.  
  382.     LastMousex=Mousex;
  383.     LastMousey=Mousey;
  384.  
  385.     do    {
  386.         for(wid=1;wid<MAX_WINDOWS;wid++)
  387.             {
  388.             if(GLWindow[wid])
  389.                 {
  390.                 /* check if window has moved (no Intuition event for this) */
  391.                 get_dimensions(wid,TRUE,&originx,&originy,&sizex,&sizey);
  392.                 originy=ScreenHeight-originy-sizey;
  393.  
  394.                 if(originx!=LastOrigin[wid][0] || originy!=LastOrigin[wid][1])
  395.                     {
  396.                     if(QDEBUG)
  397.                         printf("MOVEWINDOW (pseudo-event)\n");
  398.  
  399.                     LastOrigin[wid][0]=originx;
  400.                     LastOrigin[wid][1]=originy;
  401.  
  402.                     if(wid==waitid)
  403.                         waited=TRUE;
  404.                     }
  405.  
  406.                 userport=GLWindow[wid]->UserPort;
  407.                 inside=is_inside(wid,Mousex,Mousey,TRUE);
  408.                 if(inside)
  409.                     {
  410.                     border=!is_inside(wid,Mousex,Mousey,FALSE);
  411.  
  412.                     /* not considered inside if on border */
  413.                     inside=!border;
  414.                     }
  415.                 else
  416.                     border=FALSE;
  417.  
  418.                 while(message=(struct IntuiMessage *)GetMsg(userport))
  419.                     {
  420.                     device=0;
  421.                     data=0;
  422.  
  423.                     class=message->Class;
  424.                     code=message->Code;
  425.                     qualifier=message->Qualifier;
  426.                     mx=message->MouseX;
  427.                     my=message->MouseY;
  428.  
  429. /*    Note: ignoring button info from refresh and newsize to prevent
  430.  *    false-positive leftmouse after a resize
  431.  */
  432.  
  433.                     if( class!=NEWSIZE && class!=REFRESHWINDOW &&
  434.                                                     class!=ACTIVEWINDOW && class!=INACTIVEWINDOW )
  435.                         {
  436.                         ButtonState[LEFTMOUSE]= (qualifier&IEQUALIFIER_LEFTBUTTON)!=0;
  437.                         ButtonState[MIDDLEMOUSE]= (qualifier&IEQUALIFIER_MIDBUTTON)!=0;
  438.                         ButtonState[RIGHTMOUSE]= (qualifier&IEQUALIFIER_RBUTTON)!=0;
  439.                         }
  440.                 
  441.                     if(QDEBUG)
  442.                         printf("Msg on %d: %d,%d mb=%d%d%d code=%d ",wid,mx,my,ButtonState[LEFTMOUSE],
  443.                                                 ButtonState[MIDDLEMOUSE],ButtonState[RIGHTMOUSE],code);
  444.  
  445.                     ReplyMsg((struct Message *)message);
  446.  
  447.                     switch(class)
  448.                         {
  449.                         case CLOSEWINDOW:
  450.                             if(QDEBUG)
  451.                                 printf("CLOSEWINDOW\n");
  452.                             device=WINQUIT;
  453.                             data=TRUE;
  454.                             break;
  455.  
  456.                         case NEWSIZE:
  457.                             if(QDEBUG)
  458.                                 printf("NEWSIZE\n");
  459.  
  460. #if FALSE
  461.                             /* window resize indicates an otherwise unseen left mouse release */
  462.                             ButtonState[LEFTMOUSE]=FALSE;
  463.  
  464. #endif
  465.                             if(wid==waitid)
  466.                                 waited=TRUE;
  467.                             break;
  468.  
  469.                         case REFRESHWINDOW:
  470.                             if(QDEBUG)
  471.                                 printf("REFRESHWINDOW\n");
  472.  
  473.                             /* optimally refresh occurs between these, but not convenient in GL */
  474.                             BeginRefresh(GLWindow[wid]);
  475.                             EndRefresh(GLWindow[wid],TRUE);
  476.  
  477.                             device=REDRAW;
  478.                             data=wid;
  479.  
  480.                             drawborder(wid,0);
  481.                             break;
  482.  
  483.                         case ACTIVEWINDOW:
  484.                             if(QDEBUG)
  485.                                 printf("ACTIVEWINDOW\n");
  486.  
  487.                             if(GLFocus!=0)
  488.                                 qenter_tie(INPUTCHANGE,(short)0);
  489.  
  490.                             old_wid=GLFocus;
  491.                             GLFocus=wid;
  492.                             device=INPUTCHANGE;
  493.                             data=wid;
  494.  
  495.                             drawborder(old_wid,0);
  496.                             drawborder(wid,0);
  497.  
  498.                             RedoBorder[wid]=TRUE;
  499.                             RedoBorder[old_wid]=TRUE;
  500.                             break;
  501.  
  502.                         case INACTIVEWINDOW:
  503.                             if(QDEBUG)
  504.                                 printf("INACTIVEWINDOW\n");
  505.  
  506.                             if(GLFocus==wid)
  507.                                 {
  508.                                 old_wid=GLFocus;
  509.                                 GLFocus=0;
  510.                                 device=INPUTCHANGE;
  511.                                 data=0;
  512.                                 clear_buttons(FALSE);
  513.  
  514.                                 drawborder(old_wid,0);
  515.                                 RedoBorder[old_wid]=TRUE;
  516.                                 }
  517.  
  518.                             break;
  519.  
  520.                         case MOUSEMOVE:
  521.                             if(QDEBUG)
  522.                                 printf("MOUSEMOVE\n");
  523.  
  524.                             if(inside)
  525.                                 {
  526.                                 if(Queued[MOUSEX])
  527.                                     qenter(MOUSEX,Mousex);
  528.                                 if(Queued[MOUSEY])
  529.                                     qenter(MOUSEY,Mousey);
  530.                                 }
  531.                             break;
  532.  
  533.                         case MOUSEBUTTONS:
  534.                             if(QDEBUG)
  535.                                 printf("MOUSEBUTTONS\n");
  536.  
  537.                             switch(code)
  538.                                 {
  539.                                 case SELECTDOWN:
  540.                                     device=LEFTMOUSE;
  541.                                     data=TRUE;
  542.  
  543.                                     if(border)
  544.                                         border_touch=wid;
  545.                                     break;
  546.  
  547.                                 case SELECTUP:
  548.                                     device=LEFTMOUSE;
  549.                                     data=FALSE;
  550.                                     break;
  551.  
  552.                                 case MIDDLEDOWN:
  553.                                     device=MIDDLEMOUSE;
  554.                                     data=TRUE;
  555.  
  556.                                     if(border)
  557.                                         border_touch= -wid;
  558.                                     break;
  559.  
  560.                                 case MIDDLEUP:
  561.                                     device=MIDDLEMOUSE;
  562.                                     data=FALSE;
  563.                                     break;
  564.  
  565.                                 case MENUDOWN:
  566.                                     device=RIGHTMOUSE;
  567.                                     data=TRUE;
  568.                                     break;
  569.  
  570.                                 case MENUUP:
  571.                                     device=RIGHTMOUSE;
  572.                                     data=FALSE;
  573.                                     break;
  574.                                 }
  575.  
  576. /*
  577.                             if(!inside)
  578.                                 device=NULL;
  579. */
  580.                             break;
  581.  
  582.                         case RAWKEY:
  583.                             if(QDEBUG)
  584.                                 printf("RAWKEY\n");
  585.  
  586.                             if(inside)
  587.                                 {
  588.                                 if(!(code&IECODE_UP_PREFIX))
  589.                                     {
  590.                                     InEvent.ie_Code=code;
  591.                                     InEvent.ie_Qualifier=qualifier;
  592.                                     length=RawKeyConvert(&InEvent,string,MAXKEYINPUT,NULL);
  593.  
  594.                                     if(length>0)
  595.                                         {
  596.                                         string[length]=0;
  597.  
  598.                                         if(QDEBUG)
  599.                                             for(c=0;string[c];c++)
  600.                                                 printf("     %2x %3d '%c'\n",
  601.                                                                         string[c],string[c],string[c]);
  602.  
  603.                                         if(Queued[KEYBD] && length==1)
  604.                                             {
  605.                                             ascii=string[0];
  606.                                             device=KEYBD;
  607.                                             data=ascii;
  608.                                             }
  609.                                         }
  610.                                     }
  611.                                 }
  612.                             quekeys(code,inside);
  613.  
  614. #if FALSE
  615.                             /* prevent running */
  616.                             mess1=(struct IntuiMessage *) userport->mp_MsgList.lh_Head;
  617.                             while(mess2=(struct IntuiMessage *)mess1->ExecMessage.mn_Node.ln_Succ)
  618.                                 {
  619.                                 if(mess2->ExecMessage.mn_Node.ln_Succ==NULL)
  620.                                     break;
  621.                                 if(mess1->Class!=RAWKEY)
  622.                                     break;
  623.                                 if(!(mess1->Qualifier & IEQUALIFIER_REPEAT))
  624.                                     break;
  625.                                 if(mess2->Class != RAWKEY)
  626.                                     break;
  627.                                 if(!(mess2->Qualifier & IEQUALIFIER_REPEAT))
  628.                                     break;
  629.  
  630.                                 /* Message removed */
  631.                                 mess1=(struct IntuiMessage *)GetMsg(userport);
  632.                                 ReplyMsg((struct Message *)mess1);
  633.  
  634.                                 mess1=(struct IntuiMessage *) userport->mp_MsgList.lh_Head;
  635.                                 }
  636. #endif
  637.                             break;
  638.                         }
  639.  
  640.                     if(device && Queued[device])
  641.                         qenter_tie(device,data);
  642.                     }
  643.                 }
  644.             }
  645.         } while(waitid>=0 && !waited);
  646.  
  647.     if(border_touch && waitid<0)
  648.         {
  649.         if(border_touch<0)
  650.             {
  651.             border_touch= -border_touch;
  652.             data=TRUE;
  653.             }
  654.         else
  655.             data=FALSE;
  656.  
  657.         border_action(border_touch,Mousex,Mousey,data);
  658.         }
  659.     }
  660.  
  661.  
  662. /******************************************************************************
  663. void    qenter_tie(long device,short data)
  664.  
  665. ******************************************************************************/
  666. /*PROTOTYPE*/
  667. void qenter_tie(long device,short data)
  668.     {
  669.     short n;
  670.  
  671.     qenter(device,data);
  672.  
  673.     for(n=0;n<2;n++)
  674.         {
  675.         if(Tie[device][n]==MOUSEX)
  676.             qenter(MOUSEX,Mousex);
  677.         if(Tie[device][n]==MOUSEY)
  678.             qenter(MOUSEY,Mousey);
  679.         }
  680.     }
  681.  
  682.  
  683. /******************************************************************************
  684. void    quekeys(USHORT code,short inside)
  685.  
  686. ******************************************************************************/
  687. /*PROTOTYPE*/
  688. void quekeys(USHORT code,short inside)
  689.     {
  690.     long device;
  691.     short data=TRUE;
  692.  
  693.     if( code & IECODE_UP_PREFIX )
  694.         {
  695.         data=FALSE;
  696.         code-=IECODE_UP_PREFIX;
  697.         }
  698.  
  699.     if(code<KEYMAPLENGTH)
  700.         {
  701.          device=KeyRemap[code];
  702.  
  703.         if(data != ButtonState[device])
  704.             {
  705.             if(QDEBUG)
  706.                 printf("Code %2X %3d -> device=%d\n",code,data,device);
  707.  
  708.             ButtonState[device]=data;
  709.  
  710.             if(Queued[device] && inside)
  711.                 qenter_tie(device,data);
  712.             }
  713.         }
  714.     }
  715.  
  716.  
  717. /******************************************************************************
  718. short     is_inside(long wid,short x,short y,short border)
  719.  
  720.     if border==TRUE, will also report inside if on border
  721.  
  722. ******************************************************************************/
  723. /*PROTOTYPE*/
  724. short is_inside(long wid,short x,short y,short border)
  725.     {
  726.     long posx,posy,lenx,leny;
  727.     short inside;
  728.  
  729.     get_dimensions(wid,border,&posx,&posy,&lenx,&leny);
  730.  
  731.     x-=posx;
  732.     y-=posy;
  733.  
  734.     inside=    x>=0 && x<lenx && y>=0 && y<leny;
  735.  
  736. /*     printf("border=%d pos=%d,%d len=%d,%d %d,%d inside=%d\n",border,posx,posy,lenx,leny,x,y,inside); */
  737.  
  738.     return inside;
  739.     }
  740.  
  741.  
  742. /******************************************************************************
  743. short    border_edge(long wid,short x,short y)
  744.  
  745.     returns which edge/corner is touched as sum of the following
  746.         BORDER_LEFT
  747.         BORDER_RIGHT
  748.         BORDER_TOP
  749.         BORDER_BOTTOM
  750.         BORDER_MENU
  751.         BORDER_MINIMIZE
  752.         BORDER_MAXIMIZE
  753.  
  754.     note that all combinations of flags are not possible
  755.  
  756.     assuming you know x,y is on the border, return of 0 indicates title bar
  757. ******************************************************************************/
  758. /*PROTOTYPE*/
  759. short border_edge(long wid,short x,short y)
  760.     {
  761.     long posx,posy,lenx,leny;
  762.  
  763.     short result=0;
  764.  
  765.     get_dimensions(wid,TRUE,&posx,&posy,&lenx,&leny);
  766.  
  767.     x-=posx;
  768.     y-=posy;
  769.  
  770.     if(x< BorderWidth+BorderHeight)
  771.         result+=BORDER_LEFT;
  772.  
  773.     if(x> lenx - (BorderWidth+BorderHeight) )
  774.         result+=BORDER_RIGHT;
  775.  
  776.     if(y< BorderWidth+BorderHeight)
  777.         result+=BORDER_BOTTOM;
  778.  
  779.     if(y>= leny - (BorderWidth+BorderHeight) )
  780.         result+=BORDER_TOP;
  781.  
  782.     if( x>= BorderWidth && x< lenx-BorderWidth && y>= BorderWidth && y< leny-BorderWidth )
  783.         {
  784.         /* not on outer edge */
  785.  
  786.         if( y <= leny-BorderWidth-BorderHeight )
  787.             result=0;
  788.         else
  789.             {
  790.             /* title bar */
  791.  
  792.             if( x< BorderWidth+BorderHeight )
  793.                 result=BORDER_MENU;
  794.             else if( x>= lenx-BorderWidth-BorderHeight )
  795.                 result=BORDER_MAXIMIZE;
  796.             else if( x>= lenx-BorderWidth-2*BorderHeight )
  797.                 result=BORDER_MINIMIZE;
  798.             else
  799.                 result=0;
  800.             }
  801.         }
  802.  
  803.     return result;
  804.     }
  805.  
  806.  
  807. /******************************************************************************
  808. void     border_action(long wid,short ox,short oy,short middle)
  809.  
  810. ******************************************************************************/
  811. /*PROTOTYPE*/
  812. void border_action(long wid,short ox,short oy,short middle)
  813.     {
  814.     long old_wid;
  815.     long dx,dy;
  816.     long x,y;
  817.     long movex,movey;
  818.     long sizex,sizey;
  819.     long posx,posy,lenx,leny;
  820.     long edge=BORDER_TITLE;
  821.  
  822.     short first=TRUE;
  823.     short movefirst;
  824.  
  825.     get_dimensions(wid,TRUE,&posx,&posy,&lenx,&leny);
  826.     posy=ScreenHeight-posy-leny;
  827.  
  828.     edge=border_edge(wid,ox,oy);
  829.  
  830.     if( (middle || !Sizeable[wid]) && edge!=BORDER_MENU)
  831.         edge=BORDER_TITLE;
  832.  
  833.     if(edge==BORDER_MENU)
  834.         {
  835.         drawborder(wid,1);
  836.  
  837.         while( (!middle && getbutton(LEFTMOUSE)) || (middle && getbutton(MIDDLEMOUSE)) )
  838.             /* NOP */ ;
  839.  
  840.         drawborder(wid,0);
  841.  
  842.         qenter(WINQUIT,TRUE);
  843.         }
  844.     else if(edge==BORDER_MINIMIZE)
  845.         {
  846.         drawborder(wid,3);
  847.  
  848.         while( (!middle && getbutton(LEFTMOUSE)) || (middle && getbutton(MIDDLEMOUSE)) )
  849.             /* NOP */ ;
  850.  
  851.         drawborder(wid,0);
  852.         }
  853.     else if(edge==BORDER_MAXIMIZE)
  854.         {
  855.         drawborder(wid,4);
  856.  
  857.         while( (!middle && getbutton(LEFTMOUSE)) || (middle && getbutton(MIDDLEMOUSE)) )
  858.             /* NOP */ ;
  859.  
  860.         get_dimensions(wid,FALSE,&posx,&posy,&lenx,&leny);
  861.  
  862.         x=Maximization[wid][0];
  863.         y=Maximization[wid][1];
  864.         dx=x+Maximization[wid][2]-1;
  865.         dy=y+Maximization[wid][3]-1;
  866.  
  867. /*
  868.         printf("\n%d,%d %d,%d,%d,%d %d,%d\n",ScreenWidth,ScreenHeight,
  869.                                                                 BorderWidth,BorderHeight,x,y,dx,dy);
  870. */
  871.         old_wid=winget();
  872.         winset(wid);
  873.  
  874.         winposition(x,dx,y,dy);
  875.  
  876.         Maximization[wid][0]=posx;
  877.         Maximization[wid][1]=posy;
  878.         Maximization[wid][2]=lenx;
  879.         Maximization[wid][3]=leny;
  880.  
  881.         winset(old_wid);
  882.         }
  883.     else
  884.         {
  885.         if(!middle && edge==0)
  886.             drawborder(wid,2);
  887.  
  888.         while( (!middle && getbutton(LEFTMOUSE)) || (middle && getbutton(MIDDLEMOUSE)) )
  889.             {
  890.             x=getvaluator(MOUSEX);
  891.             y=getvaluator(MOUSEY);
  892.  
  893.             dx=x-ox;
  894.             dy=y-oy;
  895.  
  896.             if(dx || dy)
  897.                 {
  898.                 if(first)
  899.                     {
  900.                     first=FALSE;
  901.  
  902.                     GLScreen->RastPort.BitMap=VisibleRPort->BitMap;
  903.                     GLScreen->ViewPort.RasInfo->BitMap=VisibleRPort->BitMap;
  904.  
  905.                     MakeScreen(GLScreen);
  906.                     RethinkDisplay();
  907.                     }
  908.  
  909.                 sizex=0;
  910.                 sizey=0;
  911.  
  912.                 movefirst=TRUE;
  913.  
  914.                 if(edge==0)
  915.                     {
  916.                     movex=dx;
  917.                     movey= -dy;
  918.                     }
  919.                 else
  920.                     {
  921.                     movex=0;
  922.                     movey=0;
  923.                     }
  924.  
  925.                 if(edge&BORDER_TOP)
  926.                     {
  927.                     movey= -dy;
  928.                     sizey=dy;
  929.  
  930.                     movefirst= (movey<0);
  931.                     }
  932.  
  933.                 if(edge&BORDER_BOTTOM)
  934.                     sizey= -dy;
  935.  
  936.                 if(edge&BORDER_LEFT)
  937.                     {
  938.                     movex=dx;
  939.                     sizex= -dx;
  940.  
  941.                     movefirst= (movex<0);
  942.                     }
  943.  
  944.                 if(edge&BORDER_RIGHT)
  945.                     sizex=dx;
  946.  
  947.                 if(movex< -posx)
  948.                     {
  949.                     movex= -posx;
  950.                     if(sizex)
  951.                         sizex= -movex;
  952.                     }
  953.  
  954.                 if(movey< -posy)
  955.                     {
  956.                     movey= -posy;
  957.                     if(sizey)
  958.                         sizey= -movey;
  959.                     }
  960.  
  961.                 move_and_resize(wid,movefirst,movex,movey,sizex,sizey);
  962.  
  963.                 if(!middle && edge==0)
  964.                     drawborder(wid,2);
  965.  
  966.                 posx+=movex;
  967.                 posy+=movey;
  968.  
  969.                 lenx+=sizex;
  970.                 leny+=sizey;
  971.                 }
  972.  
  973.             ox=x;
  974.             oy=y;
  975.             }
  976.  
  977.         drawborder(wid,0);
  978.  
  979.         clone_new_bitmap();
  980.         }
  981.     }
  982.  
  983.  
  984. /******************************************************************************
  985. void    do_move_and_resize(long wid,long movefirst,long movex,long movey,
  986.                                                         long sizex,long sizey)
  987.  
  988.     does proper setup for double buffering
  989.     calls move_and_resize()
  990.  
  991. ******************************************************************************/
  992. /*PROTOTYPE*/
  993. void do_move_and_resize(long wid,long movefirst,long movex,long movey,long sizex,long sizey)
  994.     {
  995. /*     printf("do(%d,%d, %d,%d, %d,%d)\n",wid,movefirst,movex,movey,sizex,sizey); */
  996.  
  997.     GLScreen->RastPort.BitMap=VisibleRPort->BitMap;
  998.     GLScreen->ViewPort.RasInfo->BitMap=VisibleRPort->BitMap;
  999.  
  1000.     MakeScreen(GLScreen);
  1001.     RethinkDisplay();
  1002.  
  1003.     move_and_resize(wid,movefirst,movex,movey,sizex,sizey);
  1004.  
  1005.     clone_new_bitmap();
  1006.     }
  1007.  
  1008.  
  1009. /******************************************************************************
  1010. void    move_and_resize(long wid,long movefirst,long movex,long movey,
  1011.                                                         long sizex,long sizey)
  1012.  
  1013. ******************************************************************************/
  1014. /*PROTOTYPE*/
  1015. void move_and_resize(long wid,long movefirst,long movex,long movey,long sizex,long sizey)
  1016.     {
  1017.     long posx,posy,lenx,leny;
  1018.     long limit;
  1019.  
  1020.     get_dimensions(wid,TRUE,&posx,&posy,&lenx,&leny);
  1021.     posy=ScreenHeight-posy-leny;
  1022.  
  1023. /*
  1024.     printf("\n wid=%d movefirst=%d pos=%d,%d+%d,%d size=%d,%d+%d,%d\n",wid,movefirst,posx,posy,
  1025.                                                                 movex,movey,lenx,leny,sizex,sizey);
  1026. */
  1027.  
  1028.     if(lenx+sizex<MIN_WINX)
  1029.         sizex=MIN_WINX-lenx;
  1030.  
  1031.     if(leny+sizey<MIN_WINY)
  1032.         sizey=MIN_WINY-leny;
  1033.  
  1034.     limit=ScreenWidth-posx-lenx-sizex;
  1035.     if(movex>limit && limit>=0)
  1036.         movex=limit;
  1037.  
  1038.     limit=ScreenHeight-posy-leny-sizey;
  1039.     if(movey>limit && limit>=0)
  1040.         movey=limit;
  1041.  
  1042.     if(movex< -posx)
  1043.         movex= -posx;
  1044.  
  1045.     if(movey< -posy)
  1046.         movey= -posy;
  1047.  
  1048.     limit=ScreenWidth-posx-lenx-movex;
  1049.     if(sizex>limit && limit>=0)
  1050.         sizex=limit;
  1051.  
  1052.     limit=ScreenHeight-posy-leny-movey;
  1053.     if(sizey>limit && limit>=0)
  1054.         sizey=limit;
  1055.  
  1056. /*
  1057.     printf("                   pos=%d,%d+%d,%d size=%d,%d+%d,%d\n",posx,posy,movex,movey,
  1058.                                                                             lenx,leny,sizex,sizey);
  1059. */
  1060.  
  1061.     if( movefirst && (movex || movey) )
  1062.         {
  1063.         MoveWindow(GLWindow[wid],movex,movey);
  1064.         update_queue(wid);
  1065.         }
  1066.  
  1067.     if(sizex || sizey)
  1068.         {
  1069.         SizeWindow(GLWindow[wid],sizex,sizey);
  1070.         update_queue(wid);
  1071.  
  1072.         clear_void(wid,sizex,sizey);
  1073.         }
  1074.  
  1075.     if( !movefirst && (movex || movey) )
  1076.         {
  1077.         MoveWindow(GLWindow[wid],movex,movey);
  1078.         update_queue(wid);
  1079.         }
  1080.     }
  1081.  
  1082.  
  1083. /******************************************************************************
  1084. void    clear_void(long wid,short x,short y)
  1085.  
  1086.     clears space left by expanding window
  1087. ******************************************************************************/
  1088. /*PROTOTYPE*/
  1089. void clear_void(long wid,short x,short y)
  1090.     {
  1091.     struct RastPort *rp;
  1092.  
  1093.     long posx,posy,lenx,leny;
  1094.  
  1095.     rp=GLWindow[wid]->RPort;
  1096.  
  1097.     get_dimensions(wid,TRUE,&posx,&posy,&lenx,&leny);
  1098.  
  1099.     SetAPen(rp,0);
  1100.  
  1101.     deactivate_clipping(wid);
  1102.  
  1103.     if(x>0)
  1104.         RectFill(rp,lenx-BorderWidth-x,BorderWidth+BorderHeight,lenx-BorderWidth,leny-BorderWidth);
  1105.  
  1106.     if(y>0)
  1107.         RectFill(rp,BorderWidth,leny-BorderWidth-y,lenx-BorderWidth,leny-BorderWidth);
  1108.  
  1109.     activate_clipping(wid);
  1110.     }
  1111.